<template>
  <BasicDrawer v-bind="$attrs" @register="registerDrawer" showFooter :title="getTitle" width="50%" @ok="handleSubmit">
    <BasicForm @register="registerForm">
      <template #menuIds>
        <BasicTree :checkedKeys="checkedKeys" :treeData="treeData" checkable @check="handleCheck" title="分配菜单" />
      </template>
    </BasicForm>
  </BasicDrawer>
</template>
<script lang="ts">
import { defineComponent, ref, computed, unref } from 'vue';
import { BasicForm, useForm } from '/@/components/Form/index';
import { formSchema } from './index-option';
import { BasicDrawer, useDrawerInner } from '/@/components/Drawer';
import { getMenuSelectTreeApi } from '/@/api/sys/menu';
import { saveRoleApi, updateRoleApi, getRoleInfoApi } from '/@/api/sys/role';
import { useMessage } from '/@/hooks/web/useMessage';
import { BasicTree } from '/@/components/Tree';
import { TreeNode } from '/@/api/sys/model/treeModel';
import { getOrgTreeApi } from '/@/api/sys/org';
import { ScopeTypeEnum } from '/@/enums/sysEnum';

export default defineComponent({
  name: 'RoleDrawer',
  components: { BasicDrawer, BasicForm, BasicTree },
  emits: ['success', 'register'],
  setup(_, { emit }) {
    const treeData = ref([]);
    const checkedKeys = ref([]);
    const halfCheckedKeys = ref([]);
    const parentIds = ref(new Set<string>());
    const treeCheck = ref(false);
    const isUpdate = ref(true);
    const roleId = ref();
    const orgTreeData = ref([]);
    const orgParentIds = ref(new Set<string>());

    const { createMessage } = useMessage();
    const getTitle = computed(() => (!unref(isUpdate) ? '新增角色' : '编辑角色'));

    const [registerForm, { resetFields, setFieldsValue, validate, updateSchema }] = useForm({
      labelWidth: 110,
      schemas: formSchema,
      showActionButtonGroup: false,
      baseColProps: { lg: 24, md: 24 },
    });

    const [registerDrawer, { setDrawerProps, closeDrawer }] = useDrawerInner(async (data) => {
      await resetFields();
      await resetMenus();
      const res = await getMenuSelectTreeApi();
      treeData.value = res.data;
      const orgRes = await getOrgTreeApi();
      orgTreeData.value = orgRes.data;
      updateSchema({
        field: 'orgIds',
        componentProps: {
          treeData: orgTreeData.value
        },
      });
      isUpdate.value = !!data?.isUpdate;
      if (unref(isUpdate)) {
        // 获取角色信息，包含其菜单权限信息
        roleId.value = data.record.roleId;
        const result = await getRoleInfoApi(roleId.value);
        // 将父节点从选中节点中过滤，否则会导致全选其子菜单
        filterParentMenus(parentIds.value, res.data);
        checkedKeys.value = result.data.menuIds.filter((item) => !parentIds.value.has(item));
        halfCheckedKeys.value = result.data.menuIds.filter((item) => parentIds.value.has(item));
        if (result.data.scope == ScopeTypeEnum.CUSTOM) {
          filterParentOrgs(orgParentIds.value, orgTreeData.value);
          let orgIds = result.data.orgIds.split(',');
          result.data.orgIds = orgIds.filter((item) => !orgParentIds.value.has(item));
        }
        setFieldsValue({
          ...result.data,
        });
      }
      setDrawerProps({ confirmLoading: false });
    });

    function filterParentMenus(pIds: Set<string>, menus: Array<TreeNode>) {
      menus.forEach((item) => {
        if (item.children) {
          pIds.add(item.key);
          filterParentMenus(pIds, item.children);
        }
      });
    }

    function filterParentOrgs(pIds: Set<string>, orgs: Array<TreeNode>) {
      orgs.forEach((item) => {
        if (item.children) {
          pIds.add(item.key);
          filterParentOrgs(pIds, item.children);
        }
      });
    }

    async function handleSubmit() {
      try {
        const values = await validate();
        const menuIds = [...checkedKeys.value, ...halfCheckedKeys.value];
        setDrawerProps({ confirmLoading: true });
        let res;
        values.menuIds = menuIds;
        if (unref(isUpdate)) {
          const param = { ...values, roleId: roleId.value };
          res = await updateRoleApi(param);
        } else {
          res = await saveRoleApi(values);
        }
        createMessage.success(res.msg);
        closeDrawer();
        emit('success');
      } finally {
        setDrawerProps({ confirmLoading: false });
      }
    }

    // 树节点选中事件
    function handleCheck(keys, e) {
      if (!unref(treeCheck)) {
        treeCheck.value = true;
      }
      checkedKeys.value = keys;
      halfCheckedKeys.value = e.halfCheckedKeys;
    }

    async function resetMenus() {
      checkedKeys.value = [];
      halfCheckedKeys.value = [];
      treeData.value = [];
      parentIds.value.clear;
      treeCheck.value = false;
    }

    return {
      treeData,
      checkedKeys,
      registerDrawer,
      registerForm,
      getTitle,
      handleSubmit,
      handleCheck,
    };
  },
});
</script>
